/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package tcc.ejb.controleProjeto.controle;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import tcc.ejb.controleProjeto.controle.exceptions.IllegalOrphanException;
import tcc.ejb.controleProjeto.controle.exceptions.NonexistentEntityException;
import tcc.ejb.controleProjeto.controle.exceptions.PreexistingEntityException;
import tcc.ejb.controleProjeto.entidade.Projeto;
import tcc.ejb.controleProjeto.entidade.Artefato;
import java.util.ArrayList;
import java.util.List;
import tcc.ejb.controleProjeto.entidade.Diario;
import tcc.ejb.controleProjeto.entidade.Atividade;
import tcc.ejb.controleProjeto.entidade.Release;

/**
 *
 * @author Maciel
 */
public class ReleaseJpaController {

    public ReleaseJpaController() {
        emf = Persistence.createEntityManagerFactory("WebApplication4PU");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Release release) throws PreexistingEntityException, Exception {
        if (release.getArtefatoList() == null) {
            release.setArtefatoList(new ArrayList<Artefato>());
        }
        if (release.getDiarioList() == null) {
            release.setDiarioList(new ArrayList<Diario>());
        }
        if (release.getAtividadeList() == null) {
            release.setAtividadeList(new ArrayList<Atividade>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Projeto projeto = release.getProjeto();
            if (projeto != null) {
                projeto = em.getReference(projeto.getClass(), projeto.getId());
                release.setProjeto(projeto);
            }
            List<Artefato> attachedArtefatoList = new ArrayList<Artefato>();
            for (Artefato artefatoListArtefatoToAttach : release.getArtefatoList()) {
                artefatoListArtefatoToAttach = em.getReference(artefatoListArtefatoToAttach.getClass(), artefatoListArtefatoToAttach.getId());
                attachedArtefatoList.add(artefatoListArtefatoToAttach);
            }
            release.setArtefatoList(attachedArtefatoList);
            List<Diario> attachedDiarioList = new ArrayList<Diario>();
            for (Diario diarioListDiarioToAttach : release.getDiarioList()) {
                diarioListDiarioToAttach = em.getReference(diarioListDiarioToAttach.getClass(), diarioListDiarioToAttach.getId());
                attachedDiarioList.add(diarioListDiarioToAttach);
            }
            release.setDiarioList(attachedDiarioList);
            List<Atividade> attachedAtividadeList = new ArrayList<Atividade>();
            for (Atividade atividadeListAtividadeToAttach : release.getAtividadeList()) {
                atividadeListAtividadeToAttach = em.getReference(atividadeListAtividadeToAttach.getClass(), atividadeListAtividadeToAttach.getId());
                attachedAtividadeList.add(atividadeListAtividadeToAttach);
            }
            release.setAtividadeList(attachedAtividadeList);
            em.persist(release);
            if (projeto != null) {
                projeto.getReleaseList().add(release);
                projeto = em.merge(projeto);
            }
            for (Artefato artefatoListArtefato : release.getArtefatoList()) {
                Release oldReleaseOfArtefatoListArtefato = artefatoListArtefato.getRelease();
                artefatoListArtefato.setRelease(release);
                artefatoListArtefato = em.merge(artefatoListArtefato);
                if (oldReleaseOfArtefatoListArtefato != null) {
                    oldReleaseOfArtefatoListArtefato.getArtefatoList().remove(artefatoListArtefato);
                    oldReleaseOfArtefatoListArtefato = em.merge(oldReleaseOfArtefatoListArtefato);
                }
            }
            for (Diario diarioListDiario : release.getDiarioList()) {
                Release oldReleaseOfDiarioListDiario = diarioListDiario.getRelease();
                diarioListDiario.setRelease(release);
                diarioListDiario = em.merge(diarioListDiario);
                if (oldReleaseOfDiarioListDiario != null) {
                    oldReleaseOfDiarioListDiario.getDiarioList().remove(diarioListDiario);
                    oldReleaseOfDiarioListDiario = em.merge(oldReleaseOfDiarioListDiario);
                }
            }
            for (Atividade atividadeListAtividade : release.getAtividadeList()) {
                Release oldReleaseOfAtividadeListAtividade = atividadeListAtividade.getRelease();
                atividadeListAtividade.setRelease(release);
                atividadeListAtividade = em.merge(atividadeListAtividade);
                if (oldReleaseOfAtividadeListAtividade != null) {
                    oldReleaseOfAtividadeListAtividade.getAtividadeList().remove(atividadeListAtividade);
                    oldReleaseOfAtividadeListAtividade = em.merge(oldReleaseOfAtividadeListAtividade);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findRelease(release.getId()) != null) {
                throw new PreexistingEntityException("Release " + release + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Release release) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Release persistentRelease = em.find(Release.class, release.getId());
            Projeto projetoOld = persistentRelease.getProjeto();
            Projeto projetoNew = release.getProjeto();
            List<Artefato> artefatoListOld = persistentRelease.getArtefatoList();
            List<Artefato> artefatoListNew = release.getArtefatoList();
            List<Diario> diarioListOld = persistentRelease.getDiarioList();
            List<Diario> diarioListNew = release.getDiarioList();
            List<Atividade> atividadeListOld = persistentRelease.getAtividadeList();
            List<Atividade> atividadeListNew = release.getAtividadeList();
            List<String> illegalOrphanMessages = null;
            for (Artefato artefatoListOldArtefato : artefatoListOld) {
                if (!artefatoListNew.contains(artefatoListOldArtefato)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Artefato " + artefatoListOldArtefato + " since its release field is not nullable.");
                }
            }
            for (Diario diarioListOldDiario : diarioListOld) {
                if (!diarioListNew.contains(diarioListOldDiario)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Diario " + diarioListOldDiario + " since its release field is not nullable.");
                }
            }
            for (Atividade atividadeListOldAtividade : atividadeListOld) {
                if (!atividadeListNew.contains(atividadeListOldAtividade)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Atividade " + atividadeListOldAtividade + " since its release field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (projetoNew != null) {
                projetoNew = em.getReference(projetoNew.getClass(), projetoNew.getId());
                release.setProjeto(projetoNew);
            }
            List<Artefato> attachedArtefatoListNew = new ArrayList<Artefato>();
            for (Artefato artefatoListNewArtefatoToAttach : artefatoListNew) {
                artefatoListNewArtefatoToAttach = em.getReference(artefatoListNewArtefatoToAttach.getClass(), artefatoListNewArtefatoToAttach.getId());
                attachedArtefatoListNew.add(artefatoListNewArtefatoToAttach);
            }
            artefatoListNew = attachedArtefatoListNew;
            release.setArtefatoList(artefatoListNew);
            List<Diario> attachedDiarioListNew = new ArrayList<Diario>();
            for (Diario diarioListNewDiarioToAttach : diarioListNew) {
                diarioListNewDiarioToAttach = em.getReference(diarioListNewDiarioToAttach.getClass(), diarioListNewDiarioToAttach.getId());
                attachedDiarioListNew.add(diarioListNewDiarioToAttach);
            }
            diarioListNew = attachedDiarioListNew;
            release.setDiarioList(diarioListNew);
            List<Atividade> attachedAtividadeListNew = new ArrayList<Atividade>();
            for (Atividade atividadeListNewAtividadeToAttach : atividadeListNew) {
                atividadeListNewAtividadeToAttach = em.getReference(atividadeListNewAtividadeToAttach.getClass(), atividadeListNewAtividadeToAttach.getId());
                attachedAtividadeListNew.add(atividadeListNewAtividadeToAttach);
            }
            atividadeListNew = attachedAtividadeListNew;
            release.setAtividadeList(atividadeListNew);
            release = em.merge(release);
            if (projetoOld != null && !projetoOld.equals(projetoNew)) {
                projetoOld.getReleaseList().remove(release);
                projetoOld = em.merge(projetoOld);
            }
            if (projetoNew != null && !projetoNew.equals(projetoOld)) {
                projetoNew.getReleaseList().add(release);
                projetoNew = em.merge(projetoNew);
            }
            for (Artefato artefatoListNewArtefato : artefatoListNew) {
                if (!artefatoListOld.contains(artefatoListNewArtefato)) {
                    Release oldReleaseOfArtefatoListNewArtefato = artefatoListNewArtefato.getRelease();
                    artefatoListNewArtefato.setRelease(release);
                    artefatoListNewArtefato = em.merge(artefatoListNewArtefato);
                    if (oldReleaseOfArtefatoListNewArtefato != null && !oldReleaseOfArtefatoListNewArtefato.equals(release)) {
                        oldReleaseOfArtefatoListNewArtefato.getArtefatoList().remove(artefatoListNewArtefato);
                        oldReleaseOfArtefatoListNewArtefato = em.merge(oldReleaseOfArtefatoListNewArtefato);
                    }
                }
            }
            for (Diario diarioListNewDiario : diarioListNew) {
                if (!diarioListOld.contains(diarioListNewDiario)) {
                    Release oldReleaseOfDiarioListNewDiario = diarioListNewDiario.getRelease();
                    diarioListNewDiario.setRelease(release);
                    diarioListNewDiario = em.merge(diarioListNewDiario);
                    if (oldReleaseOfDiarioListNewDiario != null && !oldReleaseOfDiarioListNewDiario.equals(release)) {
                        oldReleaseOfDiarioListNewDiario.getDiarioList().remove(diarioListNewDiario);
                        oldReleaseOfDiarioListNewDiario = em.merge(oldReleaseOfDiarioListNewDiario);
                    }
                }
            }
            for (Atividade atividadeListNewAtividade : atividadeListNew) {
                if (!atividadeListOld.contains(atividadeListNewAtividade)) {
                    Release oldReleaseOfAtividadeListNewAtividade = atividadeListNewAtividade.getRelease();
                    atividadeListNewAtividade.setRelease(release);
                    atividadeListNewAtividade = em.merge(atividadeListNewAtividade);
                    if (oldReleaseOfAtividadeListNewAtividade != null && !oldReleaseOfAtividadeListNewAtividade.equals(release)) {
                        oldReleaseOfAtividadeListNewAtividade.getAtividadeList().remove(atividadeListNewAtividade);
                        oldReleaseOfAtividadeListNewAtividade = em.merge(oldReleaseOfAtividadeListNewAtividade);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = release.getId();
                if (findRelease(id) == null) {
                    throw new NonexistentEntityException("The release with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Release release;
            try {
                release = em.getReference(Release.class, id);
                release.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The release with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            List<Artefato> artefatoListOrphanCheck = release.getArtefatoList();
            for (Artefato artefatoListOrphanCheckArtefato : artefatoListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Release (" + release + ") cannot be destroyed since the Artefato " + artefatoListOrphanCheckArtefato + " in its artefatoList field has a non-nullable release field.");
            }
            List<Diario> diarioListOrphanCheck = release.getDiarioList();
            for (Diario diarioListOrphanCheckDiario : diarioListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Release (" + release + ") cannot be destroyed since the Diario " + diarioListOrphanCheckDiario + " in its diarioList field has a non-nullable release field.");
            }
            List<Atividade> atividadeListOrphanCheck = release.getAtividadeList();
            for (Atividade atividadeListOrphanCheckAtividade : atividadeListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Release (" + release + ") cannot be destroyed since the Atividade " + atividadeListOrphanCheckAtividade + " in its atividadeList field has a non-nullable release field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Projeto projeto = release.getProjeto();
            if (projeto != null) {
                projeto.getReleaseList().remove(release);
                projeto = em.merge(projeto);
            }
            em.remove(release);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Release> findReleaseEntities() {
        return findReleaseEntities(true, -1, -1);
    }

    public List<Release> findReleaseEntities(int maxResults, int firstResult) {
        return findReleaseEntities(false, maxResults, firstResult);
    }

    private List<Release> findReleaseEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Release.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Release findRelease(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Release.class, id);
        } finally {
            em.close();
        }
    }

    public int getReleaseCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Release> rt = cq.from(Release.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

}
